#pragma once
/*--------------------------------------------------------------------------------
 * Adaptive Intelligence - Foundation Framework Class Library
 * Version 2.00
 * 
 * Generic Collection Base Enumerator Class
 *     The abstract base class for supporting enumerations over collection  
 * class implementations.
 *--------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------
 * System Imports
 *-------------------------------------------------------------------------*/
#include "stdafx.h"
#include "GenericCollectionBase.h"

using namespace System;
using namespace System::Collections::Generic;

namespace Adaptive
{
	namespace Foundation
	{
		/// <summary>
		/// The abstract base class for supporting enumerations over collection  
		/// class implementations.
		/// </summary>
		/// <remarks>
		/// <b>AdaptiveCollectionBaseEnumerator</b> is the base class for all custom collection enumerator
		/// classes.<br/>
		/// <br/>
		///	Enumerators only allow reading the data in the collection. Enumerators cannot be used to 
		///	modify the underlying collection.<br/>
		///<br/>
		///Initially, the enumerator is positioned before the first element in the collection. 
		///<see cref="Reset"/> also brings the enumerator back to this position. At this position, 
		///calling <see cref="Current"/> throws an exception. Therefore, you must call <see cref="MoveNext"/> 
		///to advance the enumerator to the first element of the collection before reading the value of 
		///<b>Current</b>.<br/>
		///<br/>
		///<b>Current</b> returns the same object until either <b>MoveNext</b> or <b>Reset</b> is called. 
		///<b>MoveNext</b> sets <b>Current</b> to the next element.
		/// </remarks>
		generic<typename T>
		public ref class GenericCollectionBaseEnumerator : public System::Collections::Generic::IEnumerator<T>
		{
			/*---------------------------------------------------------------------------
			 * Constructor/Dispose/Destructor Methods
			 *-------------------------------------------------------------------------*/
		public:
			/// <summary>
			/// Initializes a new instance of the class.
			/// </summary>
			/// <remarks>
			/// This is the default constructor.
			/// </remarks>
			/// <param name="parentCollection">
			/// The parent collection being enumerated.
			/// </param>
			GenericCollectionBaseEnumerator(System::Collections::Generic::ICollection<T>^ parentCollection);
			/// <summary>
			/// Deallocates internally allocated objects.
			/// </summary>
			~GenericCollectionBaseEnumerator();
			/// <summary>
			/// Deallocates internally allocated objects.
			/// </summary>
			!GenericCollectionBaseEnumerator();

			/*---------------------------------------------------------------------------
			 * Public Properties
			 *-------------------------------------------------------------------------*/
			/// <summary>
			/// Gets the current element in the collection.
			/// </summary>
			/// <remarks>
			/// After an enumerator is created or after a <see cref="Reset"/>, <see cref="MoveNext"/> 
			/// must be called to advance the enumerator to the first element of the collection before 
			/// reading the value of <b>Current</b>; otherwise, <b>Current</b> is undefined.
			///	<b>Current</b> also throws an exception if the last call to <b>MoveNext</b> returned 
			///	false, which indicates the end of the collection.
			///
			/// <b>Current</b> does not move the position of the enumerator and consecutive calls to 
			/// <b>Current</b> return the same object until either <b>MoveNext</b> or 
			/// <b>Reset</b> is called.
			///
			///An enumerator remains valid as long as the collection remains unchanged. If changes are 
			///made to the collection, such as adding, modifying or deleting elements, the enumerator 
			///is irrecoverably invalidated and the next call to <b>MoveNext</b> or <b>Reset</b> throws 
			///an <see cref="InvalidOperationException"/>. If the collection is modified between 
			///<b>MoveNext</b> and <b>Current</b>, <b>Current</b> will return the element that it is 
			///set to, even if the enumerator is already invalidated.
			/// </remarks>
			/// <value>
			/// The current element in the collection.
			/// </value>
			property Object^ CurrentObject
			{
				virtual Object^ get() sealed = System::Collections::IEnumerator::Current::get;
			}
			/// <summary>
			/// Gets the current element in the collection.
			/// </summary>
			/// <remarks>
			/// After an enumerator is created or after a <see cref="Reset"/>, <see cref="MoveNext"/> 
			/// must be called to advance the enumerator to the first element of the collection before 
			/// reading the value of <b>Current</b>; otherwise, <b>Current</b> is undefined.
			///	<b>Current</b> also throws an exception if the last call to <b>MoveNext</b> returned 
			///	false, which indicates the end of the collection.
			///
			/// <b>Current</b> does not move the position of the enumerator and consecutive calls to 
			/// <b>Current</b> return the same object until either <b>MoveNext</b> or 
			/// <b>Reset</b> is called.
			///
			///An enumerator remains valid as long as the collection remains unchanged. If changes are 
			///made to the collection, such as adding, modifying or deleting elements, the enumerator 
			///is irrecoverably invalidated and the next call to <b>MoveNext</b> or <b>Reset</b> throws 
			///an <see cref="InvalidOperationException"/>. If the collection is modified between 
			///<b>MoveNext</b> and <b>Current</b>, <b>Current</b> will return the element that it is 
			///set to, even if the enumerator is already invalidated.
			/// </remarks>
			/// <value>
			/// The current element in the collection.
			/// </value>
			property T Current
			{
				virtual T get();
			}

			/*---------------------------------------------------------------------------
			 * Public Methods/Functions
			 *-------------------------------------------------------------------------*/
			/// <summary>
			/// Advances the enumerator to the next element of the collection.
			/// </summary>
			/// <remarks>
			/// After an enumerator is created or after a call to <see cref="Reset"/>, an enumerator 
			/// is positioned before the first element of the collection, and the first call to 
			/// <see cref="MoveNext"/> moves the enumerator over the first element of the collection.
			/// </remarks>
			/// <returns>
			/// <b>true</b> if the enumerator was successfully advanced to the next element; 
			/// <b>false</b> if the enumerator has passed the end of the collection.
			/// </returns>
			virtual bool MoveNext();
			/// <summary>
			/// Sets the enumerator to its initial position, which is before the first element in the 
			/// collection.
			/// </summary>
			/// <remarks>
			/// An enumerator remains valid as long as the collection remains unchanged. If changes are made 
			/// to the collection, such as adding, modifying or deleting elements, the enumerator is 
			/// irrecoverably invalidated and the next call to <see cref="MoveNext"/> or <see cref="Reset"/> 
			/// throws an <see cref="InvalidOperationException"/>.
			/// </remarks>
			virtual void Reset();

		private:
			/*---------------------------------------------------------------------------
			 * Private Declarations
			 *-------------------------------------------------------------------------*/
			/// <summary>
			/// Pointer to parent.
			/// </summary>
			System::Collections::Generic::ICollection<T>^ _parentCollection;
			/// <summary>
			/// Enumeration index.
			/// </summary>
			int _index;
		};
	}
}
